/**
 * @file tree.js.
 * @author liaoxuezhi@baidu.com
 */
/* eslint-disable */

export const findPaths = (tree, predicate) => {
  const finder = (list) => {
    const paths = [];
    list.every((item) => {
      let arr;

      if (predicate(item)) {
        paths.unshift(item);
        return false;
      } else if (item.children && (arr = finder(item.children, predicate)) && arr.length) {
        paths.unshift(item);
        paths.unshift.apply(paths, arr);
        return false;
      }

      return true;
    });

    return paths;
  };

  return finder(tree, predicate);
};

export const findPathsById = (tree, id) => {
  id = parseInt(id, 10);
  return findPaths(tree, item => item.id === id);
};

export const find = (tree, predicate) => {
  return findPaths(tree, predicate)[0];
};

export const findById = (tree, id) => {
  return findPathsById(tree, id)[0];
};

export const findByKey = (tree, key) => {
  return find(tree, item => item.key === key);
};

export const map = (tree, iterator, childKey = 'children', afterIterator) => {
  return tree.map((item, index) => {
    const newItem = iterator(item, index);

    if (item.children) {
      newItem[childKey] = map(item.children, iterator, childKey, afterIterator);
    }

    afterIterator && afterIterator(newItem);
    return newItem;
  });
};

export const filter = (tree, iterator, level = 0) => {
  return tree
    .map((item, index) => {
      const ret = iterator(item, index, level);

      if (ret && item.children) {
        item.children = filter(item.children, iterator, level + 1);

        if (!item.children || !item.children.length) {
          delete item.children;
        }
      }

      if (!ret) {
        return null;
      }

      return item;
    })
    .filter(item => item);
};
